home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Development Platforms / Apple II / Essentials / Technical.Notes / IIGS / TN.IIGS.035 < prev    next >
Encoding:
Text File  |  1990-09-21  |  38.5 KB  |  969 lines  |  [TEXT/pdos]

  1. Apple II
  2. Technical Notes
  3. _____________________________________________________________________________
  4.                                                   Developer Technical Support
  5.  
  6. Apple IIgs
  7. #35:    Printer Driver Specifications
  8.  
  9. Revised by:    Matt Deatherage                                 September 1990
  10. Written by:    Dan Hitchens, Matt Deatherage & Suki Lee              May 1988
  11.  
  12. This Technical Note describes the routines and internal structures needed to 
  13. design a printer driver for the Apple IIgs system, and you should use this 
  14. Note with the Apple IIgs Toolbox Reference manuals.  An overview and 
  15. associated parameters for each of the printer driver routines are in the Print 
  16. Manager chapter, and you should refer to these for a complete picture.
  17. Changed since March 1990:  Added corrections and further descriptions.
  18. _____________________________________________________________________________
  19.  
  20.  
  21. Printing Modes
  22.  
  23. There are two printing modes:  immediate and deferred.
  24.  
  25. o  In immediate mode, pages are printed as they are drawn into the 
  26.    printing grafPort.  As the application makes QuickDraw II calls, 
  27.    the printer driver immediately generates commands, transferring 
  28.    ink to page when the page is closed.  This is the fastest form of 
  29.    printing, but only produces high-quality images on printers that 
  30.    can translate QuickDraw II commands to other graphic commands.  
  31.    For example, the LaserWriter driver translates the QuickDraw II 
  32.    calls into PostScript(R) calls which can produce high-quality 
  33.    images.
  34.  
  35. o  In deferred mode (sometimes referred to as spool mode), pages are 
  36.    captured to memory or disk and printed after all pages have been 
  37.    defined.  Most printer drivers use deferred mode to create high-
  38.    quality images.  Since most drivers cannot obtain enough memory to 
  39.    image an entire page at once, they redraw page in several pieces, 
  40.    or bands.  The printer driver creates a grafPort whose boundsRect, 
  41.    portRect, clipRgn, and visRgn correspond to the band and plays the 
  42.    picture back, thus causing the saved commands to draw only the 
  43.    images which fall within the band.  Once the pixel image for the 
  44.    band is created, the printer driver converts the image to printer 
  45.    codes and sends the codes to the printer through the port driver.
  46.  
  47.  
  48. File Structure
  49.  
  50. The user can install new printer drivers into the system by copying a printer 
  51. driver file into a subdirectory called DRIVERS within the SYSTEM subdirectory.  
  52. The printer driver file must be of type $BB and have an auxiliary type of 
  53. $0001.
  54.  
  55.  
  56.  
  57. Print Driver Calls
  58.  
  59. A printer driver must support the following calls:
  60.  
  61.     PrDefault             $0913    Sets print record to default
  62.     PrValidate            $0A13    Validates print record
  63.     PrStlDialog           $0B13    Performs a style dialog
  64.     PrJobDialog           $0C13    Performs a job dialog
  65.     PrPixelMap            $0D13    Prints a pixel map
  66.     PrOpenDoc             $0E13    Opens the document
  67.     PrCloseDoc            $0F13    Closes the document
  68.     PrOpenPage            $1013    Opens a page
  69.     PrClosePage           $1113    Closes a page
  70.     PrPicFile             $1213    Prints a picture file
  71.     --RESERVED--          $1313
  72.     PrError               $1413    Gets the error value
  73.     PrSetError            $1513    Sets the error value
  74.     GetDeviceName         $1713    Gets device's name
  75.     PrDriverVer           $2313    Gets installed driver version
  76.  
  77. Printer drivers may support the following calls if they use the new driver 
  78. structure outlined below:
  79.  
  80.     PrGetPrinterSpecs     $1813    Returns printer type and characteristics
  81.     PrGetPgOrientation    $3813    Returns page orientation
  82.  
  83.  
  84. Print Driver Entry
  85.  
  86. o  For older drivers, entry is at the first byte (no offset).  For newer 
  87.    (Print Manager 3.0 and later) drivers, the first word is $0000, indicating 
  88.    a new style driver.  The next word is a count of how many calls this driver 
  89.    supports.  All drivers must support the minimum call set.  Additional calls 
  90.    must be supported in the sequence listed (for example, if a driver supports 
  91.    PrGetPgOrientation, it must also support PrGetPrinterSpecs).
  92. o  The Print Manager places an index to the correct routine in the X register 
  93.    (see the example and note the specific ordering of the routines) .
  94. o  There are two long return addresses (six bytes) that have been pushed onto 
  95.    the stack.  (You must take these addresses into account to access the 
  96.    parameters and to return correctly.)
  97.  
  98. Example
  99.  
  100. StartOfNewDriver    START
  101.  
  102.                     dc i2'0'                           ; new style driver
  103.                     dc i2'(ListEnd-PrDriverList)/4'    ; count
  104.  
  105.                     jmp (PrDriverList,x)
  106.  
  107.  
  108. PrDriverList        dc a4'PrDefault'
  109.                     dc a4'PrValidate'
  110.                     dc a4'PrStlDialog'
  111.                     dc a4'PrJobDialog'
  112.                     dc a4'PrDriverVer'
  113.                     dc a4'PrOpenDoc'
  114.                     dc a4'PrCloseDoc'
  115.                     dc a4'PrOpenPage'
  116.                     dc a4'PrClosePage'
  117.                     dc a4'PrPicFile'
  118.                     dc a4'InvalidRoutine'
  119.                     dc a4'PrError'
  120.                     dc a4'PrSetError'
  121.                     dc a4'GetDeviceName'
  122.                     dc a4'PrPixelMap'
  123.                     dc a4'PrGetPrinterSpecs'
  124.                     dc a4'PrGetPgOrientation'
  125. ListEnd             anop
  126.  
  127. In previous versions of this Note, the PrPixelMap and PrDriverVer entries were 
  128. reversed.
  129.  
  130. Note that when using the above technique, you're using a 16-bit jump into a 
  131. table of 24-bit addresses.  If all your entry points are in the same segment, 
  132. this is not a problem.
  133.  
  134. If your routines' entry points are not all in the same segment, you need a 
  135. dispatching routine like the following:
  136.  
  137. StartOfNewDriver    START
  138.  
  139.                     dc i2 '0'                           ; new style driver
  140.                     dc i2 '(ListEnd-PrDriverList)/4'    ; count
  141.  
  142.                     lda PrDriverList+2,x
  143.                     sep #$20
  144.                     pha                                 ; push high byte of 
  145. ;                                                         address
  146.                     rep #$20
  147.                     lda PrDriverList,x
  148.                     dec a                               ; decrement low 2 
  149. ;                                                         bytes only
  150.                     pha                                 ; push modified low 
  151. ;                                                         word of address
  152.                     rtl                                 ; transfer to the 
  153. ;                                                         routine
  154.  
  155. See Apple IIgs Technical Note #90, 65816 Tips and Pitfalls, for a discussion 
  156. of dispatching with RTL.
  157.  
  158.  
  159. Print Driver Exit
  160.  
  161. When one of your routines is ready to exit, it needs to remove the input 
  162. parameters from the stack, leaving the result space (if any) and the two RTL 
  163. addresses.  Set the accumulator and the carry flag to reflect any error you 
  164. are returning, then perform an RTL.
  165.  
  166.  
  167. Example
  168.  
  169. If there are N bytes of input parameters to remove, use something like the 
  170. following.  This code assumes that the error code is in the accumulator.
  171.  
  172.                     tay                                 ; keep error code in Y 
  173. ;                                                         temporarily
  174.                     lda 5,s
  175.                     sta N+5,s
  176.                     lda 3,s
  177.                     sta N+3,s
  178.                     lda 1,s
  179.                     sta N+1,s
  180.                     tsc
  181.                     clc
  182.                     adc #N
  183.                     tcs
  184.                     tya                                 ; get error code
  185.                     cmp #1                              ; set carry if error 
  186. ;                                                         is not zero
  187.                     rtl
  188.  
  189. Figure 1 diagrams the stack just before exiting the print driver:
  190.  
  191.     |
  192.     | Previous Contents
  193.     |___________________
  194.     |
  195.     | Results (if any)
  196.     |___________________
  197.     |
  198.     | RTL2 (3 bytes)
  199.     |___________________
  200.     |
  201.     | RTL1 (3 bytes)
  202.     |___________________
  203.  
  204.                         <-- Stack Pointer
  205.  
  206.     Figure 1-Stack Prior to Exiting the Print Driver
  207.  
  208. You should do an RTL with the contents of the flags and registers set 
  209. appropriately.  (See the Return from Call section of the "Using The Apple 
  210. Tools" chapter of the Apple IIgs Toolbox Reference.)
  211.  
  212.  
  213. Print Record Structure
  214.  
  215. Since application programs often need to fiddle with parts of the print record 
  216. (i.e., the values in the style subrecord), we have defined ways for 
  217. applications to interpret the print record, and specifically the style 
  218. subrecord.
  219.  
  220. iDev, the first word of the printer information subrecord, has two defined 
  221. values for third-party printer drivers.  A value of $8001 indicates a dot-
  222. matrix printer while a value of $8003 indicates a laser printer.
  223.  
  224. A value of $8001 indicates that fields of the style subrecord should be 
  225. interpreted as they are by the ImageWriter driver, as documented in the Apple 
  226. IIgs Toolbox Reference.  The first seven bits (0-6) of wDev are defined as for 
  227. the ImageWriter driver.  Bits 7-11 are reserved for Apple's use and must be 
  228. set to zero.  Bits 12-15 may be used by third-party printer drivers as 
  229. necessary; these bits are set to zero in Apple's drivers.
  230.  
  231. A value of $8003 indicates that fields of the style subrecord should be 
  232. interpreted as they are by the LaserWriter driver.  The first four bits (0-3) 
  233. of wDev are defined as for the LaserWriter driver.  Bits 4-11 are reserved for 
  234. Apple's use and must be set to zero.  Bits 12-15 may be used by third-party 
  235. printer drivers as necessary; these bits are set to zero in Apple's drivers.
  236.  
  237. If an application wishes to take advantages of specific features of a third-
  238. party printer driver, it has to know that it is dealing with that driver.  
  239. Since all drivers look pretty much alike, the Print Manager allows you to ask 
  240. for the name of the currently selected printer driver.  An application may 
  241. make the Print Manager call PMGetPrinterName, which is documented in Volume 3 
  242. of the Toolbox Reference.  The Print Manager returns the name of the currently 
  243. selected printer in a Pascal (length byte) string.  The name returned is the 
  244. name of the file from which the driver was loaded.  If you intend to use this 
  245. method to identify a driver, you must inform users not to rename the Printer 
  246. Driver file on the boot disk.
  247.  
  248. For alternate driver identification, Developer Technical Support assigns new 
  249. iDev values if you feel it is absolutely necessary for your driver.  Please 
  250. keep in mind, however, that no application knows how to interpret style 
  251. records for non-standard iDev values, and that Apple does not publish such 
  252. interpretations.
  253.  
  254.  
  255. Print Driver Calls
  256.  
  257. Your printer driver handles the following calls:
  258.  
  259. PrDefault                            ($0913)
  260.  
  261. Description:
  262.     Fills the fields of the specified print record with default values for the 
  263.     printer.
  264.  
  265. Passed:
  266.     PrintRecordHandle                LONG    Handle to the print record
  267.  
  268. Returned:
  269.     None
  270.  
  271. Performs the following:
  272. o  Validates that PrintRecordHandle is a handle and does nothing if not.
  273. o  Determines the default values for the print record either through tables or 
  274.    calculations.  The default values should take into account such things as 
  275.    paper size and orientation, print mode, printer type, etc.
  276. o  Copies the default values to the print record specified by the 
  277.    PrintRecordHandle parameter.
  278.  
  279. PrValidate                           ($0A13)
  280.  
  281. Description:
  282.     Checks the print record to see that it is valid for the currently installed 
  283.     printer driver.
  284.  
  285. Passed:
  286.     PrintRecordHandle                LONG    Handle to the print record
  287.  
  288. Returned:
  289.     ChangeFlag                       WORD    Boolean; TRUE if the record is 
  290.                                              adjusted
  291.  
  292. Performs the following:
  293. o  Checks to see if the print record is from this particular driver.
  294. o  If the print record is not from this driver, it uses the default values for 
  295.    this driver.
  296. o  If the print record is from this driver, it makes any changes that might be 
  297.    needed (i.e., style, paper size, etc.).
  298.  
  299. PrStlDialog                          ($0B13)
  300.  
  301. Description:
  302.     Performs a style dialog with the user.
  303.  
  304. Passed:
  305.     PrintRecordHandle                LONG    Handle to the print record
  306.  
  307. Returned:
  308.     ConfirmFlag                      WORD    Boolean; TRUE if the dialog is 
  309.                                              confirmed
  310.  
  311. Performs the following:
  312. o  Conducts a style dialog with the user to determine the page dimensions and 
  313.    other information needed for page setup (the initial settings of the dialog 
  314.    are derived from the print record).
  315. o  If the user confirms the dialog, the information from the dialog is saved 
  316.    in the specified print record, PrValidate is called, and the routine 
  317.    returns TRUE.
  318. o  If the user cancels the dialog, the print record is left unchanged, and the 
  319.    routine returns FALSE.
  320.  
  321. Note:  The following are items typically found in printer style dialogs:
  322.  
  323. o  Paper Size (US Letter, US Legal, A4 Letter, B5 Letter, International 
  324.    Fanfold)
  325. o  Printing Orientation (Landscape, Portrait)
  326. o  Vertical Sizing (Normal, Intermediate, Condensed)
  327. o  Special Effects:
  328.         Font Effects (Font Substitution, Smoothing)
  329.         Reduction or Enlargement
  330.         Gaps or No Gaps between pages
  331.  
  332. Every printer style dialog should have an OK button (default) and a Cancel 
  333. button.
  334.  
  335. Note:  When calling other routines in your printer driver (like 
  336.        PrValidate), be sure to do so through the Tool Dispatcher ($E10000 
  337.        or $E10004) so any necessary patches have an opportunity to execute.
  338.  
  339. PrJobDialog                          ($0C13)
  340.  
  341. Description:
  342.     Performs a job dialog with the user.
  343.  
  344. Passed:
  345.     PrintRecordHandle                LONG    Handle to the print record
  346.  
  347. Returned:
  348.     ConfirmFlag                      WORD    Boolean; True if the dialog is 
  349.                                              confirmed
  350.  
  351. Performs the following:
  352. o  Conducts a job dialog with the user to determine the print quality, range 
  353.    of pages to print, and other specifications.  The initial settings are 
  354.    derived from the previous PrJobDialog call (or initial default values) 
  355.    except the page range which is set to ALL, and the number of copies which 
  356.    is set to ONE.
  357. o  If the user confirms the dialog, PrValidate is called, the print record is 
  358.    updated, and the routine returns TRUE.
  359. o  If the user cancels the dialog, the print record is left unchanged, and the 
  360.    routine returns FALSE.
  361.  
  362. Note:  The following are items typically found in printer job dialogs:
  363.  
  364.        o  Print Quality (Best, Faster, Draft, etc.)
  365.        o  Color option
  366.        o  Pages (All, Range)
  367.        o  Copies
  368.        o  Paper Source (paper cassette, manual feed)
  369.  
  370. Every printer job dialog should have an OK button (default) and a Cancel 
  371. button.
  372.  
  373. Note:  When calling other routines in your printer driver (like 
  374.        PrValidate), be sure to do so through the Tool Dispatcher ($E10000 
  375.        or $E10004) so any necessary patches have an opportunity to 
  376.        execute.
  377.  
  378. PrPixelMap                           ($0D13)
  379.  
  380. Description:
  381.     Prints all or part of the specified pixel map.
  382.  
  383. Passed:
  384.     srcLocPtr                        LONG    Pointer to the source LocInfo 
  385.                                              which contains the pointer to 
  386.                                              the pixel map.
  387.     srcRectPtr                       LONG    Pointer to the rectangle which
  388.                                              encloses the pixel map to be 
  389. printed.
  390.     colorFlag                        WORD    Boolean; FALSE if black and white,
  391.                                              TRUE if color.
  392.  
  393. Returned:
  394.     None
  395. Performs the following:
  396. o  Calls DevIsItSafe (port driver call) to verify that the port it functioning 
  397.    and it is safe to proceed.  If it is not functioning, set the internal 
  398.    error code to $1302 (Port Not On) and return with an error status.
  399. o  Saves the current grafPort.
  400. o  Turns on the watch cursor to signal the user that it will take some time.
  401. o  Clears the internal error code (default, if no errors occur).
  402.  
  403. You can choose to print the pixel map in any convenient fashion; one 
  404. convenient way is to allocate a new print record and call your normal printing 
  405. routines.  This method is outlined below.
  406.  
  407. o  Gets a new handle for a print record and set it to the defaults by calling 
  408.    PrDefault.
  409. o  If colorFlag is set, change the style subrecord of the print record to 
  410.    reflect color printing.
  411. o  Do any initialization that might be needed by the driver.
  412. o  Determine the intersection of the two rectangles (rectangle pointed to by 
  413.    srcRectPtr and the pixel map's boundary rectangle from srcLocPtr) and if 
  414.    there is no intersection, then nothing is to be printed.
  415. o  Print the pixel image which is within the intersection of the two 
  416.    rectangles.
  417. o  Cause a page eject to occur on the printer.
  418. o  Do any clean up that is needed.
  419. o  Turn off the watch cursor by calling InitCursor (or restore the previous 
  420.    cursor using SetCursor).
  421. o  Restore the grafPort by calling SetPort.
  422.  
  423. PrOpenDoc                            ($0E13)
  424.  
  425. Description:
  426.     This routine initializes the things needed to open a document.  In deferred 
  427.     mode, it establishes a grafPort and makes it the current port for printing.
  428.  
  429. Passed:
  430.     PrintRecordHandle                LONG    Handle to the print record
  431.     PrinterPortPtr                   LONG    Pointer to the grafPort, if 
  432.                                              desired, zero to allocate a new 
  433.                                              grafPort
  434. Returned:
  435.     PrinterPortPtrRet                LONG    Pointer to the grafPort if the
  436.                                              PrinterPortPtr was zero
  437.  
  438. Performs the following:
  439. o  Calls DevIsItSafe (port driver call) to verify that the port is functioning 
  440.    and it is safe to proceed.
  441. o  Turns on the watch cursor to signal the user that it will take some time.
  442. o  Validates the print record passed by  calling PrValidate.
  443. o  Clears the internal error code (default, if nothing happens).
  444. o  Puts up a dialog indicating that printing is occurring (or preparing to 
  445.    print).
  446. o  If the user needs a grafPort, create one and internally note that one was 
  447.    created (PrCloseDoc needs to know that one was created here).
  448. o  Initializes parameters (i.e., page number, document number, etc.).
  449. o  If deferred mode, create an initial page list (an array of handles to 
  450.    pictures) for recording pages.  You can pick an arbitrary number to start 
  451.    with (like 20).  This assumes spooling to memory; spooling to disk will 
  452.    obviously be different.
  453. o  Do other initialization that might be needed to start a print job.
  454.  
  455. Possible errors:
  456.     portNotOn                        $1302    Indicates Port Not On
  457.  
  458. PrCloseDoc                           ($0F13)
  459.  
  460. Description:
  461.     Closes the grafPort being used for printing.  For immediate mode, this 
  462.     routine ends the printing job.  For deferred mode, this routine ends the 
  463.     recording of the document to be printed.
  464.  
  465. Passed:
  466.     PrintGrafPortPtr                 LONG    Pointer to the grafPort used for 
  467.                                              printing
  468.  
  469. Returned:
  470.     None
  471.  
  472. Performs the following:
  473. o  Checks that the last print driver call did not cause a Port Not On error.  
  474.    If the error occurred, do nothing and return.
  475. o  Call ClosePort to close the printing grafPort.
  476. o  If the driver allocated a grafPort in PrOpenDoc, disposes of it.
  477. o  If in immediate mode, does what is needed to shut things down.
  478. o  Takes down the information dialog box from PrOpenDoc.
  479.  
  480.  
  481. Possible errors:
  482.     portNotOn                        $1302    Indicates Port Not On
  483.     prBozo                           $13FF    Someone unloaded the driver in 
  484.                                               the middle of the print loop
  485.  
  486. PrOpenPage                           ($1013)
  487.  
  488. Description:
  489.     Begins a new page only if the page falls within the page range specified in 
  490.     the job subrecord.
  491.  
  492. Passed:
  493.     PrintGrafPortPtr                 LONG    Pointer to the grafPort used for 
  494.                                              printing
  495.     PageFramePtr                     LONG    Pointer to the scaling parameter,
  496.                                              zero for none.
  497. Returned:
  498.     None
  499.  
  500. Performs the following:
  501. o  Looks at the driver's internal error value, and if an error has occurred, 
  502.    it returns without doing anything.
  503. o  Increments the page number.
  504. o  Calls SetPort to make the specified port the current port.
  505. o  Initializes the port and zeroes the boundary rectangle so no actual drawing 
  506.    occurs.
  507. o  If immediate mode, then do the following:
  508.         If this page is to be printed, install immediate mode procedures by 
  509.         doing the following:
  510.         o  Create a procedure table (get the standard procedures from 
  511.            SetStdProcs).
  512.         o  Put pointers to your procedures into the table and call the 
  513.            QuickDraw II routine SetGrafProcs.  This causes QuickDraw II calls 
  514.            to call your routines instead of drawing to the pixel map 
  515.            associated with the grafPort.
  516. o  If deferred mode, then do the following:
  517.    o  If the current page is out of the page range, then return without 
  518.       doing anything further.
  519.    o  If the user passes his own PageFramePtr , then get it.
  520.    o  Open a picture by calling OpenPicture and adding its handle to the 
  521.       page list array described in PrOpenDoc.
  522.    o  Set the ClipRgn and VisRgn to the sizing framing rectangle specified 
  523.       by PageFramePtr , or if none was specified, to the default of rPage.
  524.  
  525. Possible errors:
  526.     portNotOn                        $1302    Indicates Port Not On
  527.     prBozo                           $13FF    Someone unloaded the driver in 
  528.                                               the middle of the print loop
  529.  
  530. PrClosePage                          ($1113)
  531.  
  532. Description:
  533.     This signals the end of a page.
  534.  
  535. Passed:
  536.     PrintGrafPortPtr                 LONG    Pointer to the grafPort used for 
  537.                                              printing
  538.  
  539. Returned:
  540.     None
  541.  
  542. Performs the following:
  543. o  Looks at the driver's internal error value and if a Port Not On error has 
  544.    occurred, it returns without doing anything.
  545. o  If immediate mode, do the following:
  546. o  If the current page is within the range of pages to be printed, then 
  547.    cause a form feed (unless no gap was specified).
  548. o  If deferred mode, do the following:
  549. o  If there was no picture generated, then do nothing and just return.
  550. o  Restore the grafPort to the port saved in PrOpenPage.
  551. o  Do a ClosePicture to close the picture.
  552.  
  553. Possible errors:
  554.     portNotOn                        $1302    Indicates Port Not On
  555.     prBozo                           $13FF    Someone unloaded the driver in 
  556.                                               the middle of the print loop
  557.  
  558. PrPicFile                            ($1213)
  559.  
  560. Description:
  561.     Prints a picture file generated in deferred mode.
  562.  
  563. Passed:
  564.     PrintRecordHandle                LONG    Handle to the print record
  565.     PrintGrafPortPtr                 LONG    Pointer to the grafPort used for 
  566.                                              printing
  567.     StatusRecPtr                     LONG    Pointer to the printer status 
  568.                                              record
  569.  
  570. Returned:
  571.     None
  572.  
  573. Performs the following:
  574. o  Looks at the driver's internal error value and if a Port Not On error has 
  575.    occurred, it returns without doing anything.
  576. o  If immediate mode, return without doing anything.
  577. o  If deferred mode, then do the following:
  578.    o  If the error code is not zero (errors) then dispose of all the recorded 
  579.       page images.
  580.    o  Put up an information dialog indicating that printing is occurring.
  581.    o  Display a watch cursor (saving the current cursor first if you like).
  582.    o  If PrintGrafPortPtr is NIL, create one and make a note of it.
  583.    o  Call OpenPort to make the grafPort the current port.
  584.    o  If StatusRecPtr is NIL, use an internal one.  This is to simplify your 
  585.       code; if the StatusRecPtr is NIL, you can reasonably choose not to use a 
  586.       status record at all, but this requires an extra code path.
  587.    o  Initialize the status record and the number of copies counter.
  588.    o  If the idle procedure pointer in the print record is NIL, point to an 
  589.       internal one.  Again, as with the StatusRecPtr, you can choose to ignore 
  590.       idle procedures if no pointer is provided, but this requires an extra 
  591.       code path.
  592.    o  Do The Following For Each Copy:
  593.       o  Calculate the number of bands to print one page and initialize the 
  594.          page counter.
  595.       o  Do The Following For Each Page:
  596.          o  Call the idle procedure routine and initialize the band counter.
  597.          o  Get the handle to the picture associated with the current page.
  598.          o  Set the dirty flag in the status record to FALSE.
  599.          o  If manual paper feed, put up a dialog and wait for a response.
  600.          o  Do The Following For Each Band:
  601.             o  Call the idle procedure.
  602.             o  Calculate the band rectangle and update iCurBand with the 
  603.                current band number.
  604.             o  Call the idle procedure again.
  605.             o  Set the imaging flag in the status record to TRUE.
  606.             o  Call InitPort to reinitialize the port.
  607.             o  Adjust fields in the port to cause drawing into the band 
  608.                buffer.
  609.             o  Adjust fields in the location information field of the status 
  610.                record and calculate the sizing rectangle.
  611.             o  Calculate the boundary rectangle for the band and set the port 
  612.                rectangle to it.
  613.             o  Set the ClipRgn and the VisRgn to the sizing rectangle.
  614.             o  Initialize the band by filling it with white space.
  615.             o  Call DrawPicture to draw the picture into the band's 
  616.                rectangle.
  617.             o  Do whatever is needed to print the pixel image in the band's 
  618.                rectangle.
  619.             o  Clear the imaging flag.
  620.             o  Calculate the next band's position.
  621.             o  Increment the band's counter and loop back if not done.
  622.          o  If a vertical gap was specified, cause a form feed.
  623.          o  Increment the page count to the next page and loop back if not 
  624.             done.
  625.       o  Increment the number of copies counter and loop back if not done.
  626.    o  Free any buffers that you own and close the port.
  627.    o  Dispose of the information dialog that you put up.
  628.    o  Dispose of each picture in the picture list by calling KillPicture.
  629.    o  Dispose of the picture list itself.
  630.    o  Restore the cursor.
  631.  
  632. Possible errors:    
  633.     portNotOn                        $1302    Indicates Port Not On
  634.     prBozo                           $13FF    Someone unloaded the driver in 
  635.                                               the middle of the print loop
  636.  
  637. PrError                              ($1413)
  638.  
  639. Description:
  640.     Gets the error code from the last Print Manager call.
  641.  
  642. Passed:
  643.     None
  644.  
  645. Returned:
  646.     LastError                        WORD    Result code from last Print 
  647.                                              Manager call
  648.  
  649. Performs the following:
  650. o  Gets the driver's internal error value (which was determined by the last 
  651.    driver call) and sets the return parameter LastError to it.
  652.  
  653. Possible Errors:
  654.     noError                          $0000
  655.     PrAbort                          $0080    Indicates print job was aborted
  656.                                      $1301    Indicates missing drivers
  657.                                      $1302    Indicates Port Not On
  658.                                      $1303    Indicates No Print Record
  659.                                      $1306    Indicates PAP Connection Not 
  660.                                               Made
  661.                                      $1307    Indicates Read/Write PAP Error
  662.                                      $1308    Indicates Printer Connection 
  663.                                               Failed
  664.     prBozo                           $13FF    Someone unloaded the driver in 
  665.                                               the middle of the print loop
  666.  
  667. PrSetError                           ($1513)
  668.  
  669. Description:
  670.     Sets the error value.
  671.  
  672. Passed:
  673.     ErrorNumber                      WORD    Error number to be set
  674.  
  675. Returned:
  676.     None
  677.  
  678. Performs the following:
  679. o  Sets the driver's internal error value to the value of the passed 
  680.    ErrorNumber parameter.
  681.  
  682. GetDeviceName                        ($1713)
  683. (also known as PrChanged)
  684.  
  685. Description:
  686.     Used as a communications tool between the printer driver and port driver.
  687.  
  688. Passed:
  689.     None
  690.  
  691. Returned:
  692.     None
  693.  
  694. Performs the following:
  695. o  Calls the port driver routine PrDevPrChanged with the printer name as 
  696.    input.  This is necessary for drivers that work over AppleTalk.  The name 
  697.    passed as the parameter to PrDevPrChanged should be what AppleTalk uses in 
  698.    an NBPLookup situation; for AppleTalk, such a name should follow Name 
  699.    Binding Protocol conventions.
  700.  
  701.    This routine will be called by the Print Manager when your driver is first 
  702.    loaded so a network port driver can find devices of your type.  
  703.    Applications should not make this call.  When this routine will be called 
  704.    is not guaranteed; you can't use this as a substitute for a startup call.
  705.  
  706. PrDriverVer                          ($2313)
  707.  
  708. Description:
  709.     Returns the version number of the currently installed printer driver.
  710.  
  711. Passed:
  712.     Wordspace                        WORD    Space for results
  713.  
  714. Returned:
  715.     versionInfo                      WORD    Printer driver's version number
  716.  
  717. Performs the following:
  718. o  Gets the internal version number of the printer driver and returns it on 
  719.    the stack at versionInfo.
  720.  
  721. Note:  The internal version number is stored major byte, minor byte 
  722.        (i.e., $0103 represents version 1.3)
  723.  
  724. PrGetPrinterSpecs                    ($1813)
  725.  
  726. Description:
  727.     Returns the type of printer and the printer's characteristics.
  728.  
  729. Passed:
  730.     Wordspace                        WORD    Space for results
  731.     Wordspace                        WORD    Space for results
  732.  
  733. Returned:
  734.     PrinterType                      WORD    0 = undefined
  735.                                              1 = ImageWriter or ImageWriter II
  736.                                              2 = ImageWriter LQ
  737.                                              3 = LaserWriter family 
  738.                                                  (except IIsc)
  739.                                              4 = Epson
  740.                                              $8001 = generic dot matrix printer
  741.                                              $8003 = generic laser printer
  742.     PrCharacteristics                WORD    Bits 15-2 = reserved, must be zero
  743.                                              Bits 1-0:  00 = cannot determine
  744.                                                         01 = black and white 
  745.                                                              only
  746.                                                         10 = color capable
  747.  
  748. Performs the following:
  749. o    Returns characteristics intrinsic for the printer being supported.
  750.  
  751. The value returned for PrinterType should be the driver's iDev value.
  752.  
  753. PrGetPgOrientation                   ($3813)
  754.  
  755. Description:
  756.     Returns the page orientation from a print record.
  757.  
  758. Passed:
  759.     Wordspace                        WORD    Space for result
  760.     PrintRecordHandle                LONG    Handle to the print record
  761.  
  762. Returned:
  763.     PgOrientation                    WORD    Current page orientation:
  764.                                              0 = portrait
  765.                                              1 = landscape
  766.  
  767. Performs the following:
  768. o  Returns the page orientation from the current page setup information in the 
  769.    print record.
  770.  
  771.  
  772. Immediate Mode Procedures
  773.  
  774. To print in the immediate mode, you need to install procedures which cause 
  775. printing when you make QuickDraw II calls (as noted in PrOpenPage).  This 
  776. section describes the structure and parameters for these routines.
  777.  
  778. The basic idea is that your driver replaces low-level QuickDraw II routines 
  779. with pointers to your own routines.  For example, when someone wants QuickDraw 
  780. II to draw some text (say with DrawString), QuickDraw II calls your low-level 
  781. routine to draw the text.  You can then print the text instead.
  782.  
  783. To install the immediate mode procedures, first create a procedure table for 
  784. sixteen entries (16*4 bytes) and fill it with the standard procedures by 
  785. calling SetStdProcs.  Once you have the standard procedures, install the 
  786. addresses of your replacement procedures into it and call SetGrafProcs.  
  787. Installing your procedure addresses causes the appropriate QuickDraw II calls 
  788. to call your procedures, which, in turn, perform the actual printing.
  789.  
  790. The routines that need to be written are known as QuickDraw II "bottleneck 
  791. procedures."  For most dot-matrix printer drivers, the one of most concern 
  792. when writing immediate mode procedures is StdText.  If your target device has 
  793. an alternate page imaging language, you may wish to print entirely in 
  794. immediate mode.  In this case, you want to intercept most of the bottleneck 
  795. procedures.  Apple IIgs Technical Note #34, Low-Level QuickDraw II Routines, 
  796. contains information on how to install these procedures.  The sample code 
  797. which follows shows how to replace StdPixels and StdText.
  798.  
  799. Example:
  800.  
  801. ;*****************************************************************
  802. ;** Example of Immediate Mode Printer Procedures.               **
  803. ;*****************************************************************
  804. Immedprocs     Start
  805.  
  806. SrcRect        equ $DC
  807. SrcLocInfo     equ $CC
  808. DrawVerb       equ $38
  809. TextPtr        equ $da
  810. TextLength     equ $d8
  811. CharToDraw     equ $d6
  812.  
  813. ;------------------------------------------------------------------
  814. ;
  815. ; StdPixels Procedure (Prints Pixel maps)
  816. ;
  817. ;------------------------------------------------------------------
  818. Pixel          Entry
  819.  
  820.                phb                          ;save data bank reg on stack
  821.                phk                          ;get program bank reg.
  822.                plb                          ;use as data bank reg.
  823.  
  824.                lda iPrErr                   ;get errors
  825.                beq Continue                 ;branch if none
  826.                brl ExitPixel                ;branch if errors
  827.  
  828. Continue       anop
  829.  
  830. ;This gets the source rectangle and stores it at PixelRect
  831.                ldx #6
  832. MoveSrc        lda SrcRect,x
  833.                sta PixelRect,x
  834.                dex
  835.                dex
  836.                bpl MoveSrc
  837.  
  838. ;This gets the source LocInfo and stores it at PixelLoc 
  839.                ldx #16-2
  840. MoveLI         lda SrcLocInfo,x
  841.                sta PixelLoc,x
  842.                dex
  843.                dex
  844.                bpl MoveLI
  845.  
  846.                pushlong #PixelLoc           ;push pointer to LocInfo
  847.                pushlong #PixelRect          ;push pointer to rectangle
  848.  
  849.  
  850. ;++++++++++++++++++++++
  851. ; Insert code here to print a pixel map
  852. ;    INPUT:    PixelLoc   LONG, Pointer to pixel LocInfo
  853. ;              PixelRect  LONG, Pointer to pixels BoundsRect
  854. ;    SP->
  855. ;++++++++++++++++++++++
  856.  
  857. Exitpixel      lda #0                       ;return with no errors
  858.                clc
  859.                plb                          ;restore data bank
  860.                rtl                          ;return with long
  861.  
  862. PixelLoc       ds 16                        ;pixel LocInfo
  863. PixelRect      ds 8                         ;pixel rectangle
  864.  
  865. ;------------------------------------------------------------------
  866. ;
  867. ; StdText Procedure (Prints Standard Text)
  868. ;
  869. ;------------------------------------------------------------------
  870. StdText        Entry
  871.  
  872.                phb                          ;save data bank reg on stack
  873.                phk                          ;get program bank reg. 
  874.                plb                          ;use as data bank reg.
  875.  
  876.                pushlong #PenPos
  877.                _GetPen                      ;current pen pos. -> PenPos
  878.  
  879. ;++++++++++++++++++++++
  880. ; Insert Code Here to move the printers head to the corresponding
  881. ; PenPos position (if needed).
  882. ;++++++++++++++++++++++
  883.  
  884.                pushword #0                  ;space for textwidth
  885.                                             ;(for call to _TextWidth)
  886.  
  887.                lda DrawVerb                 ;get DrawVerb
  888.                beq DoCar                    ;if DrawVerb=0 then DoCar
  889.  
  890.                cmp #1
  891.                beq Dotext2                  ;if DrawVerb=1 then Dotext2
  892. ;
  893. ;We get here if it's a "C" string (DrawVerb=2)
  894. ;
  895. DoCstring      anop
  896.                sep #$20
  897.                longa off
  898. ;Search down through string looking for terminator to calc. length
  899.                ldy #0
  900. KeepLooking    lda [TextPtr],y
  901.                beq TheEnd
  902.                iny
  903.                bra KeepLooking
  904. TheEnd         rep #$20
  905.                longa on
  906.                lda TextPtr+2
  907.                pha                          ;push the pointer to string
  908.                lda Textptr
  909.                pha
  910.                phy                          ;push the length of sting
  911.                bra Common
  912.  
  913. ;
  914. ;We get here if it's just one character (DrawVerb=0)
  915. ;
  916. DoCar          anop
  917.                pushword #0
  918.                tdc
  919.                clc
  920.                adc #CharToDraw              ;calculate addr. of char.
  921.                pha                          ;push addr. of character
  922.                pushword #1                  ;push length of one char.
  923.                bra Common
  924.  
  925. ;
  926. ;We get here if it's a string of text (DrawVerb=1)
  927. ;
  928. DoText2        anop
  929.                lda TextPtr+2
  930.                pha                          ;push pointer to the string
  931.                lda Textptr
  932.                pha
  933.                lda TextLength
  934.                pha                          ;push the strings length
  935. Common         lda 5,s                      ;Dup the last 3 words of
  936.                pha                          ;the stack (for _TextWidth)
  937.                lda 5,s
  938.                pha
  939.                lda 5,s
  940.                pha
  941. ;++++++++++++++++++++++
  942. ; Insert code here to print the text
  943. ;
  944. ;    INPUT:    TextPointer    LONG, Pointer to text to print
  945. ;              TextLength     WORD, No. of bytes to print
  946. ;    SP->
  947. ;++++++++++++++++++++++
  948.                _TextWidth                   ;get the texts width (DH)
  949.                pushword #0                  ;set (DV)=0
  950.                _Move                        ;move current pen location
  951.  
  952. ExitText       lda #0                       ;return with no errors
  953.                clc
  954.                plb                          ;restore data bank
  955.                rtl                          ;returnith long
  956.  
  957. PenPos         ds 4                         ;pen position
  958.                end
  959.  
  960.  
  961. Further Reference
  962. _____________________________________________________________________________
  963.   o  Apple IIgs Toolbox Reference, Volumes 1-3
  964.   o  Apple IIgs Technical Note #36, Port Driver Specifications
  965.   o  Apple IIgs Technical Note #90, 65816 Tips and Pitfalls
  966.  
  967. PostScript is a registered trademark of Adobe Systems Incorporated.
  968.  
  969.